// 源自Inferno utils/6l/l.h和相关文件。
// https:
// None
// None
// None
// None
// None
// None
// None
// None
// None
// None
// 特此向任何获得副本的人免费授予许可
// 本软件和相关文档文件（“软件”）的
// 在软件中不受限制，包括但不限于权利
// 使用、复制、修改、合并、发布、分发、再许可和/或销售
// 软件的副本，并允许向其提供软件的人员
// 按照以下条件提供：
// None
// 上述版权声明和本许可声明应包含在
// 软件的所有副本或主要部分。
// None
// 本软件按“原样”提供，无任何形式的明示或明示担保
// 默示，包括但不限于适销性保证，
// 适用于特定目的和非侵权。在任何情况下
// 作者或版权持有人应承担任何索赔、损害或其他责任
// 无论是在合同诉讼、侵权诉讼或其他诉讼中，由以下原因引起的责任：，
// 与本软件有关或与本软件的使用或其他交易有关
// 软件。

package objabi

type RelocType int16

// go:生成stringer-type=RelocType
const (
	R_ADDR RelocType = 1 + iota
	// R_ADDRPOWER重新定位一对“D格式”指令（16位指令
	// 直接出现在指令词的下半部分），通常后跟
	// 另一个add或load，插入地址的“高调整”16位
	// 将引用符号插入第一条指令的立即数字段，然后
	// 将16位低位转换为第二条指令的16位低位。
	R_ADDRPOWER
	// R_ADDRARM64重新定位adrp，添加对以计算
	// 参考符号。
	R_ADDRARM64
	// R_ADDRMIPS（仅用于mips/mips64）解析为外部数据的低16位
	// 地址，通过将其编码到指令中。
	R_ADDRMIPS
	// R_ADDROFF解析为从节开始的32位偏移量
	// 保留要重新定位到引用符号的数据。
	R_ADDROFF
	R_SIZE
	R_CALL
	R_CALLARM
	R_CALLARM64
	R_CALLIND
	R_CALLPOWER
	// R_CALLMIPS（仅用于mips64）解析为非PC相对目标地址
	// 调用（JAL）指令，通过将地址编码到指令中。
	R_CALLMIPS
	// R_CALLRISCV标记用于堆栈检查的RISC-V调用。
	R_CALLRISCV
	R_CONST
	R_PCREL
	// 用于386、amd64和ARM的R_TLS_LE解析为
	// 线程本地基的线程本地符号，用于实现
	// tls访问的“本地执行”模型（英特尔平台上未设置r.Sym，但
	// 设置为链接器中的TLS符号（外部链接时为runtime.tlsg）。
	R_TLS_LE
	// R_TLS_IE，使用386、amd64和ARM解析到PC相对于GOT的偏移量
	// 包含从线程本地符号到线程本地符号的偏移量的插槽
	// 用于实现tls访问的“初始执行”模型（r.Sym
	// 未在英特尔平台上设置，但在中设置为TLS符号--runtime.tlsg
	// 外部链接时的链接器）。
	R_TLS_IE
	R_GOTOFF
	R_PLT0
	R_PLT1
	R_PLT2
	R_USEFIELD
	// R_USETYPE解析为*rtype，但不创建重定位。这个
	// 链接器将其用作指向类型信息的信号
	// 应该链接到最终的二进制文件中，即使没有其他
	// 直接参考。（这用于可通过反射访问的类型。）
	R_USETYPE
	// R_USEIFACE标记将类型转换为此函数中的接口
	// 重新安置适用于以下情况：。目标是一个类型描述符。
	// 这是一个标记重定位（0大小），用于链接器的可达性
	// 分析
	R_USEIFACE
	// R_USEIFACEMETHOD标记函数中使用的接口方法
	// 此重新定位适用于。目标是一个接口类型描述符。
	// 加数是类型描述符中方法的偏移量。
	// 这是一个标记重定位（0大小），用于链接器的可达性
	// 分析
	R_USEIFACEMETHOD
	// R_METHODOFF解析为从节开始的32位偏移量
	// 保留要重新定位到引用符号的数据。
	// 它是R_ADDROFF的一个变体，用于从
	// *rtype，如果链接器确定方法，则可以将其设置为零
	// 链接程序无法访问文本。
	R_METHODOFF
	// R_KEEP告诉链接器将引用的符号保留在最终二进制文件中
	// 如果包含R_KEEP重定位的符号在最终二进制中。
	R_KEEP
	R_POWER_TOC
	R_GOTPCREL
	// R_JMPMIPS（仅用于mips64）解析为非PC相对目标地址
	// 在JMP指令中，通过将地址编码到指令中。
	// 堆栈nosplit检查忽略此项，因为它不是函数调用。
	R_JMPMIPS

	// R_DWARFSECREF解析为符号与其截面的偏移量。
	// 搬迁目标必须为4号（在当前实施中）。
	R_DWARFSECREF

	// R\u DWARFFILEREF解析为DWARF.debug\u行的索引
	// 指定文件符号的文件表。必须应用于
	// 表单DW_表单_数据4的属性。
	R_DWARFFILEREF

	// 平台相关的重新定位。具有固定宽度指令的体系结构
	// 有一个固有的问题，32位（或64位！）位移不能
	// 填充到32位指令中，因此地址需要分散
	// 几条指令，而这又需要一系列的重新定位，每一条指令
	// 更新指令的一部分。这导致重新定位代码为
	// 固有的处理器特定。

	// Arm64。

	// 将MOV[NZ]立即数字段设置为距线程偏移量的位[15:0]
	// 由引用的线程定义的线程局部变量的局部基（线程
	// 本地）符号。如果偏移量不适合16位，则出错。
	R_ARM64_TLS_LE

	// 重新定位ADRP；LD64指令序列，用于加载之间的偏移量
	// 线程局部基和由
	// GOT中引用的（线程本地）符号。
	R_ARM64_TLS_IE

	// R_ARM64_GOTPCREL重新定位adrp、ld64对以计算GOT的地址
	// 引用符号的槽。
	R_ARM64_GOTPCREL

	// R_ARM64_GOT解析GET相对指令序列，通常是adrp
	// 然后是另一个ld指令。
	R_ARM64_GOT

	// R_ARM64_PCREL解析PC相对地址指令序列，通常为
	// adrp后接另一条add指令。
	R_ARM64_PCREL

	// R_ARM64_LDST8将LD/ST立即数值设置为本地地址的位[11:0]。
	R_ARM64_LDST8

	// R_ARM64_LDST16将LD/ST立即数值设置为本地地址的位[11:1]。
	R_ARM64_LDST16

	// R_ARM64_LDST32将LD/ST立即数值设置为本地地址的位[11:2]。
	R_ARM64_LDST32

	// R_ARM64_LDST64将LD/ST立即数值设置为本地地址的位[11:3]。
	R_ARM64_LDST64

	// R_ARM64_LDST128将LD/ST立即数设置为本地地址的位[11:4]。
	R_ARM64_LDST128

	// PPC64。

	// R_POWER_TLS_LE用于实现TLS的“本地执行”模型
	// 通道它解析为线程本地符号相对于
	// 线程指针（R13）并根据一对指令拆分为
	// 支持32位位移。
	R_POWER_TLS_LE

	// R_POWER_TLS_IE用于实现TLS访问的“初始执行”模型。信息技术
	// 重新定位D格式、DS格式的指令序列，如R_ADDRPOWER_DS。信息技术
	// 从TOC插入螺纹局部符号的GET插槽偏移量（
	// GET插槽由动态链接器用本地线程的偏移量填充
	// 来自线程指针（R13）的符号。
	R_POWER_TLS_IE

	// R_POWER_TLS将X形式指令（如“添加R3、R13、R4”）标记为完成
	// 计算TLS地址的一系列GET相对重定位。这可能是
	// 系统链接器用于将GET相对TLS重新定位重写为
	// 更简单的线程指针相对重新定位。见附录中的表3.26和3.28
	// 此转换上的ppc64 elfv2 1.4 ABI。同样，第二个论点
	// （在X格式指令中通常称为RB）假定为R13。
	R_POWER_TLS

	// R_ADDRPOWER_DS与上面的R_ADDRPOWER类似，但假定为第二个
	// 指令是一个“DS表单”指令，它有一个直接字段
	// 指令字的位[15:2]。地址的位[15:2]
	// 将重新定位的符号插入该字段；如果最后两个
	// 地址的位不是0。
	R_ADDRPOWER_DS

	// R_ADDRPOWER_PCREL重新定位D格式、DS格式指令序列，如
	// R_ADDRPOWER_DS，但插入引用符号的GET插槽的偏移量
	// 来自TOC，而不是符号的地址。
	R_ADDRPOWER_GOT

	// R_ADDRPOWER_PCREL像R_ADDRPOWER一样重新定位两条D格式指令，但是
	// 插入从要重新定位的位置到
	// 重新定位符号，而不仅仅是其地址。
	R_ADDRPOWER_PCREL

	// R_ADDRPOWER_TOCREL像R_ADDRPOWER一样重新定位两条D格式指令，但是
	// 插入从TOC到重新定位符号地址的偏移量
	// 而不是符号的地址。
	R_ADDRPOWER_TOCREL

	// R_ADDRPOWER_TOCREL重新定位D格式、DS格式指令序列，如
	// R_ADDRPOWER_DS，但插入从TOC到
	// 重新定位的符号，而不是符号的地址。
	R_ADDRPOWER_TOCREL_DS

	// RISC-V。

	// R_RISCV_PCREL_ITYPE使用
	// AUIPC+I型指令对。
	R_RISCV_PCREL_ITYPE

	// R_RISCV_PCREL_STYPE使用
	// AUIPC+S型指令对。
	R_RISCV_PCREL_STYPE

	// R_RISCV_TLS_IE_ITYPE解析32位TLS初始执行TOC偏移量
	// 使用AUIPC+I型指令对的地址。
	R_RISCV_TLS_IE_ITYPE

	// R_RISCV_TLS_IE_STYPE解析32位TLS初始执行TOC偏移量
	// 使用AUIPC+S型指令对的地址。
	R_RISCV_TLS_IE_STYPE

	// R_PCRELDBL重新定位s390x 2字节对齐的PC相对地址。
	// TODO（mundaym）：一旦变量可以序列化就删除-请参阅14218期。
	R_PCRELDBL

	// R_ADDRMIPSU（仅用于mips/mips64）解析为符号调整的“上限”16
	// 外部地址的位（位16-31），通过将其编码到指令中。
	R_ADDRMIPSU
	// R_ADDRMIPSTLS（仅用于mips64）解析为TLS的低16位
	// 地址（从线程指针的偏移量），通过将其编码到指令中。
	R_ADDRMIPSTLS

	// R_addrchoff解析为指针大小的从指针开始的偏移量
	// 符号的矮人编译单元。
	R_ADDRCUOFF

	// R_WASMIMPORT解析为WebAssembly函数导入的索引。
	R_WASMIMPORT

	// R_XCOFFREF（仅在aix/ppc64上使用）防止ld进行垃圾收集
	// 象征性的。这不是真正的搬迁，它可以放在任何地方
	// 在一个符号中，以任何符号为目标。
	R_XCOFFREF

	// R_弱将重新定位标记为弱引用。
	// 弱重定位不会使它所指的符号可到达，
	// 并且只有当符号以其他方式出现时，链接器才会对其表示敬意
	// 可达成的。
	R_WEAK = -1 << 15

	R_WEAKADDR    = R_WEAK | R_ADDR
	R_WEAKADDROFF = R_WEAK | R_ADDROFF
)

// IsDirectCall报告r是否是直接呼叫的重定位。
// 直接调用是采用目标地址的调用指令
// 作为一个直接的例子。地址可能嵌入到指令中
// 宽度有限。间接调用是执行以下操作的调用指令：
// 寄存器或内存中的目标地址。
func (r RelocType) IsDirectCall() bool {
	switch r {
	case R_CALL, R_CALLARM, R_CALLARM64, R_CALLMIPS, R_CALLPOWER, R_CALLRISCV:
		return true
	}
	return false
}

// IsDirectJump报告r是否是直接跳转的重新定位。
// 直接跳转是采用目标地址的JMP指令
// 作为一个直接的例子。地址可能嵌入到指令中
// 宽度有限。间接跳转是采用
// 寄存器或内存中的目标地址。
func (r RelocType) IsDirectJump() bool {
	switch r {
	case R_JMPMIPS:
		return true
	}
	return false
}

// IsDirectCallOrJump报告r是否为直接
// 呼叫或直接跳转。
func (r RelocType) IsDirectCallOrJump() bool {
	return r.IsDirectCall() || r.IsDirectJump()
}
